home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # Apple Macintosh Developer Technical Support
- #
- # MultiFinder-Aware Simple Sample Application
- #
- # CrashOMatic
- #
- # CrashOMatic.c - C Source (main segment)
- #
- # Copyright © 1989-93 Apple Computer, Inc.
- #
- #
- # This is the sample app modified for CrashOMatic functionality
- # Written by Brian Topping
- ------------------------------------------------------------------------------*/
-
-
-
- #pragma segment Main
-
- #include <Values.h>
- #include <Types.h>
- #include <Resources.h>
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <Events.h>
- #include <Windows.h>
- #include <Menus.h>
- #include <TextEdit.h>
- #include <Dialogs.h>
- #include <Desk.h>
- #include <ToolUtils.h>
- #include <Memory.h>
- #include <SegLoad.h>
- #include <Files.h>
- #include <OSUtils.h>
- #include <OSEvents.h>
- #include <DiskInit.h>
- #include <Packages.h>
- #include <Traps.h>
- //#include <MacHeaders>
- #include <MachineExceptions.h>
- #include <setjmp.h>
- #include "CrashOMatic.h"
-
- #define HiWrd(aLong) (((aLong) >> 16) & 0xFFFF)
- #define LoWrd(aLong) ((aLong) & 0xFFFF)
- #define TopLeft(aRect) (* (Point *) &(aRect).top)
- #define BotRight(aRect) (* (Point *) &(aRect).bottom)
-
- QDGlobals qd;
- static jmp_buf *curJmpBuf;
- Boolean gUseExceptionHandlers;
-
- extern void _DataInit();
-
- ////////////////////////////////////////////////////////////////////////////////
- // CrashOMatic Specific
- ////////////////////////////////////////////////////////////////////////////////
-
- // EXCEPTION HANDLER NOTES:
- // These are the same exception handlers that the memory manager uses and are
- // re-entrant so long as they are not pre-empted. They are useable as you
- // see them in your own application. The trick is to save the longjmp buffer on
- // the stack, and save the address of it in a global. When we get an
- // exception, we use the global to find the correct state to resume, and longjmp
- // through it with a non-zero error value. This causes the conditional around our
- // setjmp to go to the error handling code.
- OSErr HeapExceptionHandler(ExceptionInformation *theException)
- {
- // just get back to where we started
- // if we cared what the exception was, we could pass it
- // in place of our favorite constant, letting the app know a bit more...
- longjmp(*curJmpBuf,69);
- }
-
- void doExceptionProtected(short selection)
- {
- OSErr theErr;
- jmp_buf localJump, *oldJump;
- ExceptionHandler oldHandler;
- long illegalAddr, temp;
-
- // set up our illegal address
- illegalAddr = 0xDEADBEEF;
-
- // set up exception buffer addresses
- oldJump = curJmpBuf;
- curJmpBuf = &localJump;
-
- oldHandler = InstallExceptionHandler((ExceptionHandler)HeapExceptionHandler);
- if (theErr = setjmp(localJump)) {
- // If we wanted to do something here with the exception, we could
- // all we really want to do though is have a alternate that doesn't loop
- }
- else {
- // here is where we do the dirty deed
- switch (selection) {
- case iIllegal:
- (*((ProcPtr)0))();
- break;
- case iBusError:
- temp = *((long *)illegalAddr);
- break;
- }
- }
-
- InstallExceptionHandler(oldHandler);
- curJmpBuf = oldJump;
- }
-
- void doWithoutProtection(short selection)
- {
- long illegalAddr, temp;
-
- // set up our illegal address
- illegalAddr = 0xDEADBEEF;
-
- // here is where we do the dirty deed
- switch (selection) {
- case iIllegal:
- (*((ProcPtr)0))();
- break;
- case iBusError:
- temp = *((long *)illegalAddr);
- break;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // DTS Sample shell
- ////////////////////////////////////////////////////////////////////////////////
- main()
- {
- UnloadSeg((Ptr) _DataInit); /* note that _DataInit must not be in Main! */
-
- MaxApplZone(); /* expand the heap so code segments load at the top */
-
- Initialize(); /* initialize the program */
- UnloadSeg((Ptr) Initialize); /* note that Initialize must not be in Main! */
-
- EventLoop(); /* call the main event loop */
- }
-
-
- void EventLoop()
- {
- RgnHandle cursorRgn;
- Boolean gotEvent;
- EventRecord event;
- Point mouse;
-
- cursorRgn = NewRgn(); /* we’ll pass WNE an empty region the 1st time thru */
- do {
- GetGlobalMouse(&mouse);
- gotEvent = WaitNextEvent(everyEvent, &event, MAXLONG, cursorRgn);
-
- if ( gotEvent ) {
- DoEvent(&event);
- }
- } while ( true ); /* loop forever; we quit via ExitToShell */
- } /*EventLoop*/
-
-
- /* Do the right thing for an event. Determine what kind of event it is, and call
- the appropriate routines. */
-
- void DoEvent(EventRecord *event)
- {
- short part, err;
- WindowPtr window;
- Boolean hit;
- char key;
- Point aPoint;
-
- switch ( event->what ) {
- case mouseDown:
- part = FindWindow(event->where, &window);
- switch ( part ) {
- case inMenuBar: /* process a mouse menu command (if any) */
- DoMenuCommand(MenuSelect(event->where));
- break;
- case inSysWindow: /* let the system handle the mouseDown */
- SystemClick(event, window);
- break;
- case inDrag: /* pass screenBits.bounds to get all gDevices */
- DragWindow(window, event->where, &qd.screenBits.bounds);
- break;
- case inGrow:
- break;
- case inZoomIn:
- case inZoomOut:
- hit = TrackBox(window, event->where, part);
- if ( hit ) {
- SetPort(window); /* the window must be the current port... */
- EraseRect(&window->portRect); /* because of a bug in ZoomWindow */
- ZoomWindow(window, part, true); /* note that we invalidate and erase... */
- InvalRect(&window->portRect); /* to make things look better on-screen */
- }
- break;
- }
- break;
- case keyDown:
- case autoKey: /* check for menukey equivalents */
- key = event->message & charCodeMask;
- if ( event->modifiers & cmdKey ) /* Command key down */
- if ( event->what == keyDown ) {
- DoMenuCommand(MenuKey(key));
- }
- break;
- case diskEvt:
- if ( HiWord(event->message) != noErr ) {
- SetPt(&aPoint, kDILeft, kDITop);
- err = DIBadMount(aPoint, event->message);
- }
- break;
- }
- } /*DoEvent*/
-
-
-
- void GetGlobalMouse(Point *mouse)
- {
- EventRecord event;
-
- OSEventAvail(kNoEvents, &event); /* we aren't interested in any events */
- *mouse = event.where; /* just the mouse position */
- } /*GetGlobalMouse*/
-
-
- void DoMenuCommand(long menuResult)
- {
- short menuID; /* the resource ID of the selected menu */
- short menuItem; /* the item number of the selected menu */
- short itemHit;
- Str255 daName;
- short daRefNum;
- Boolean handledByDA;
-
- menuID = HiWord(menuResult); /* use macros for efficiency to... */
- menuItem = LoWord(menuResult); /* get menu item number and menu number */
- switch ( menuID ) {
- case mApple:
- switch ( menuItem ) {
- case iAbout: /* bring up alert for About */
- itemHit = Alert(rAboutAlert, nil);
- break;
- default: /* all non-About items in this menu are DAs */
- /* type Str255 is an array in MPW 3 */
- GetItem(GetMHandle(mApple), menuItem, daName);
- daRefNum = OpenDeskAcc(daName);
- break;
- }
- break;
- case mFile:
- switch ( menuItem ) {
- case iQuit:
- Terminate();
- break;
- }
- break;
- case mEdit: /* call SystemEdit for DA editing & MultiFinder */
- handledByDA = SystemEdit(menuItem-1); /* since we don’t do any Editing */
- break;
- case mTest:
- switch ( menuItem ) {
- case iDebugger:
- DebugStr("\pWelcome home!");
- break;
- case iClobber:
- *((long *)0) = -1;
- break;
- case iIllegal:
- case iBusError:
- if (gUseExceptionHandlers)
- doExceptionProtected(menuItem);
- else
- doWithoutProtection(menuItem); // you really should wear a raincoat!
- break;
- case iExceptionHandlers:
- gUseExceptionHandlers = (gUseExceptionHandlers ? 0:1);
- CheckItem(GetMenu(mTest),iExceptionHandlers,gUseExceptionHandlers);
- break;
- }
- break;
- }
- HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
- } /*DoMenuCommand*/
-
-
- Boolean DoCloseWindow(WindowPtr window)
- {
- if ( IsDAWindow(window) )
- CloseDeskAcc(((WindowPeek) window)->windowKind);
- return true;
- } /*DoCloseWindow*/
-
-
- void Terminate()
- {
- WindowPtr aWindow;
- Boolean closed;
-
- closed = true;
- do {
- aWindow = FrontWindow(); /* get the current front window */
- if (aWindow != nil)
- closed = DoCloseWindow(aWindow); /* close this window */
- }
- while (closed && (aWindow != nil));
- if (closed)
- ExitToShell(); /* exit if no cancellation */
- } /*Terminate*/
-
- /* Check to see if a window belongs to a desk accessory. */
-
- Boolean IsDAWindow(WindowPtr window)
- {
- if ( window == nil )
- return false;
- else /* DA windows have negative windowKinds */
- return ( ((WindowPeek) window)->windowKind < 0 );
- } /*IsDAWindow*/
-
-
- void AlertUser()
- {
- short itemHit;
-
- SetCursor(&qd.arrow);
- itemHit = Alert(rUserAlert, nil);
- ExitToShell();
- } /* AlertUser */
-
- /* Set up the whole world, including global variables, Toolbox managers,
- and menus. We also create our one application window at this time.
- Since window storage is non-relocateable, how and when to allocate space
- for windows is very important so that heap fragmentation does not occur.
- Because Sample has only one window and it is only disposed when the application
- quits, we will allocate its space here, before anything that might be a locked
- relocatable object gets into the heap. This way, we can force the storage to be
- in the lowest memory available in the heap. Window storage can differ widely
- amongst applications depending on how many windows are created and disposed. */
-
- /* 1.01 - The code that used to be part of ForceEnvirons has been moved into
- this module. If an error is detected, instead of merely doing an ExitToShell,
- which leaves the user without much to go on, we call AlertUser, which puts
- up a simple alert that just says an error occurred and then calls ExitToShell.
- Since there is no other cleanup needed at this point if an error is detected,
- this form of error- handling is acceptable. If more sophisticated error recovery
- is needed, an exception mechanism, such as is provided by Signals, can be used. */
-
- void Initialize()
- {
- Handle menuBar;
- EventRecord event;
- short count;
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- gUseExceptionHandlers = false;
-
- for (count = 1; count <= 3; count++)
- EventAvail(everyEvent, &event);
-
- menuBar = GetNewMBar(rMenuBar); /* read menus into menu bar */
- if ( menuBar == nil ) AlertUser();
- SetMenuBar(menuBar); /* install menus */
- DisposHandle(menuBar);
- AddResMenu(GetMHandle(mApple), 'DRVR'); /* add DA names to Apple menu */
- DrawMenuBar();
-
- } /*Initialize*/
-
-